/** Une classe abstraite � utiliser pour le menu de lancement du jeu
 *  La classe de menu de votre jeu doit h�riter de cette classe :
 *    - d�finir la m�thode nomOptions qui renvoie un tableau de String qui corresponds aux
 *    options possibles de votre menu
 *    - d�finir la m�thode lancerOption(int i) qui associe des actions aux options de votre menu
 *    - d�finir les m�thodes wavAccueil et wavAide qui d�signent le fichier wave � lire pour l'accueil
 *    et l'aide.
 * 
 *  Ne pas modifier cette classe
 *  @author helene
 */

package tool.devintAPI;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import javax.swing.border.LineBorder;

import t2s.SIVOXDevint;
import tool.AutoresizeTextArea;
import view.absGenericView;
import controleur.Config;

@SuppressWarnings("serial")
public abstract class MenuAbstrait2 extends absGenericView implements
		KeyListener, ActionListener
{

	// -------------------------------------------------------
	// les attributs

	private AutoresizeTextArea entete;
	private JButton[] boutonOption;
	protected final String description;
	protected Font fonteBouton;
	private final int nbOption;
	private int optionCourante;
	private GridBagConstraints regles;
	public SIVOXDevint voix;

	public int placementy = 0;
	private int optWeight = 1;
	private int enteteWeight = 2;// Sorcelerie
	private JPanel boutons;

	// -------------------------------------------------
	// les methodes abstraites a definir par heritage

	// -------------------------------------------------------
	/**
	 * constructeur,
	 * 
	 * @param title : le nom du jeu
	 * @param noms : liste des options du menu
	 */
	public MenuAbstrait2(String title, String desc, String[] nomOptions,
			Config c)
	{
		super(title, c);
		this.description = desc;
		this.optionCourante = -1;
		this.nbOption = nomOptions.length;

		// Layout et regles par default
		this.setLayout(new GridBagLayout());
		this.regles = new GridBagConstraints();
		this.regles.fill = GridBagConstraints.BOTH;
		this.regles.anchor = GridBagConstraints.NORTHWEST;
		this.regles.insets = new Insets(10, 50, 10, 50);
		this.regles.weightx = 1;
		this.regles.weighty = 1;

		// Attributs
		this.fonteBouton = new Font("Tahoma", 1, 56);

		this.creerEntete();
		this.creerOption(nomOptions);

		this.setExtendedState(Frame.MAXIMIZED_BOTH);
		this.requestFocus();
		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		this.voix = new SIVOXDevint();
		this.voix.playWav(this.wavAccueil());

		this.setConfig(this.cfg);
		this.setVisible(true);

	}

	// activer l'option si clic sur le bouton
	public void actionPerformed(ActionEvent ae)
	{
		this.voix.stop();
		Object source = ae.getSource();
		for (int i = 0; i < this.nbOption; i++)
		{
			if (source == this.boutonOption[i])
			{
				if (this.optionCourante != -1)
					this.unFocusedButton(this.optionCourante);
				this.optionCourante = i;
				this.setFocusedButton(this.optionCourante);
				this.lancerOption(i);
			}
		}
	}

	// pour creer un bouton associe e un texte
	private void creerBouton(int i, String texte)
	{
		this.boutonOption[i] = new JButton();
		this.boutonOption[i].setText(texte);
		this.setPropertiesButton(this.boutonOption[i]);
	}

	/**
	 * cree l'entete avec le nom du jeu
	 */
	public void creerEntete()
	{

		// le label

		entete = new AutoresizeTextArea(this.description);
		entete.setFont(new Font("Georgia", 1, 96));

		this.regles.weighty = enteteWeight;
		this.regles.gridx = 0;
		this.regles.gridy = placementy++;
		this.add(entete, this.regles);
	}

	// -------------------------------------------------------
	// methodes utilisees par le constructeur

	/**
	 * creer les boutons associes aux noms d'options
	 */
	private void creerOption(String[] noms)
	{

		this.boutons = new JPanel();
		boutons.setLayout(new GridLayout(this.nbOption, 1));
		// les boutons
		this.boutonOption = new JButton[this.nbOption];
		for (int i = 0; i < this.nbOption; i++)
		{
			this.creerBouton(i, noms[i]);
			boutons.add(this.boutonOption[i]);
		}

		this.regles.weighty = optWeight;
		this.regles.gridx = 0;
		this.regles.gridy = placementy++;
		this.add(boutons, this.regles);
	}

	public void keyPressed(KeyEvent e)
	{
		super.keyPressed(e);
		if (e.getKeyCode() == KeyEvent.VK_ENTER)
		{
			this.lancerOption(this.optionCourante); // methode e rendre
			// concrete par heritage
		}
		// se deplacer dans les options vers le bas
		if (e.getKeyCode() == KeyEvent.VK_DOWN)
		{
			if (this.optionCourante == -1)
			{
				this.optionCourante = 0;
				this.setFocusedButton(this.optionCourante);
			}
			else
			{
				this.unFocusedButton(this.optionCourante);
				this.optionCourante = (this.optionCourante + 1) % this.nbOption;
				this.setFocusedButton(this.optionCourante);
			}
		}
		// se deplacer dans les options vers le haut
		if (e.getKeyCode() == KeyEvent.VK_UP)
		{
			if (this.optionCourante == -1)
			{
				this.optionCourante = 0;
				this.setFocusedButton(this.optionCourante);
			}
			else
			{
				this.unFocusedButton(this.optionCourante);
				this.optionCourante = this.optionCourante - 1;
				if (this.optionCourante == -1)
					this.optionCourante = this.nbOption - 1;
				this.setFocusedButton(this.optionCourante);
			}
		}
	}

	// evenements clavier
	public void keyReleased(KeyEvent e)
	{
	}

	public void keyTyped(KeyEvent e)
	{
	}

	// methodes e definir pour rendre la classe concrete
	/**
	 * lance l'action associee au bouton nei methode abstraite e definir par
	 * heritage PRECOND : i varie entre 0 et le nombre d'options possibles moins
	 * 1
	 */
	protected abstract void lancerOption(int i);

	// -------------------------------------------------------
	// methodes pour reagir aux evenements clavier

	/**
	 * renvoie le tableau contenant le nom des options methode abstraite e
	 * definir par heritage
	 */
	// protected abstract String[] nomOptions();
	// mettre le focus sur une option
	private void setFocusedButton(int i)
	{
		this.voix.playShortText(this.boutonOption[i].getText());
		this.boutonOption[i].setBackground(this.cfg.selectbg);
		this.boutonOption[i].setForeground(this.cfg.selectfg);
	}

	// mettre e jour les proprietes des boutons
	protected void setPropertiesButton(JButton b)
	{
		b.setFocusable(false);
		b.setBackground(this.cfg.bg);
		b.setForeground(this.cfg.fg);
		b.setFont(this.fonteBouton);
		b.setBorder(new LineBorder(Color.BLACK, 5));
		b.addActionListener(this);
	}

	// enlever le focus d'une option
	private void unFocusedButton(int i)
	{
		this.boutonOption[i].setBackground(this.cfg.bg);
		this.boutonOption[i].setForeground(this.cfg.fg);
	}

	/**
	 * renvoie le nom du fichier wav e lire pour l'accueil PRECOND : fichier est
	 * le chemin pour acceder au fichier
	 */
	protected abstract String wavAccueil();

	/**
	 * renvoie le nom du fichier wav e lire pour l'aide PRECOND : fichier est le
	 * chemin pour acceder au fichier
	 */
	protected abstract String wavAide();

	@Override
	protected void init()
	{// Unused
	}

	@Override
	public void setConfig(Config c)
	{
		this.cfg = c;
		entete.setBorder(new LineBorder(this.cfg.border, 8));
		entete.setBackground(this.cfg.bg);
		entete.setForeground(this.cfg.fg);
		for (Component co : boutons.getComponents())
		{
			co.setBackground(this.cfg.bg);
			co.setForeground(this.cfg.fg);
		}
	}

}
